home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS / antlr / lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-14  |  18.2 KB  |  732 lines  |  [TEXT/MPS ]

  1. /*
  2.  * lex.c    --    Generate all of the lexical type files: parser.dlg tokens.h
  3.  *
  4.  * $Id: lex.c,v 1.8 1994/08/29 20:16:14 parrt Exp parrt $
  5.  * $Revision: 1.8 $
  6.  *
  7.  * SOFTWARE RIGHTS
  8.  *
  9.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  10.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  11.  * company may do whatever they wish with source code distributed with
  12.  * PCCTS or the code generated by PCCTS, including the incorporation of
  13.  * PCCTS, or its output, into commerical software.
  14.  * 
  15.  * We encourage users to develop software with PCCTS.  However, we do ask
  16.  * that credit is given to us for developing PCCTS.  By "credit",
  17.  * we mean that if you incorporate our source code into one of your
  18.  * programs (commercial product, research project, or otherwise) that you
  19.  * acknowledge this fact somewhere in the documentation, research report,
  20.  * etc...  If you like PCCTS and have developed a nice tool with the
  21.  * output, please mention that you developed it using PCCTS.  In
  22.  * addition, we ask that this header remain intact in our source code.
  23.  * As long as these guidelines are kept, we expect to continue enhancing
  24.  * this system and expect to make other tools available as they are
  25.  * completed.
  26.  *
  27.  * ANTLR 1.23
  28.  * Terence Parr
  29.  * Parr Research Corporation
  30.  * with Purdue University and AHPCRC, University of Minnesota
  31.  * 1989-1994
  32.  */
  33. #include <stdio.h>
  34. #include <ctype.h>
  35. #ifdef __cplusplus
  36. #ifndef __STDC__
  37. #define __STDC__
  38. #endif
  39. #endif
  40. #include "set.h"
  41. #include "syn.h"
  42. #include "hash.h"
  43. #include "generic.h"
  44.  
  45. #define DLGErrorString "invalid token"
  46.  
  47. /* Generate a complete lexical description of the lexemes found in the grammar */
  48. void
  49. #ifdef __STDC__
  50. genLexDescr( void )
  51. #else
  52. genLexDescr( )
  53. #endif
  54. {
  55.     ListNode *p;
  56.     FILE *dlgFile = fopen(OutMetaName(DlgFileName), "w");
  57.     require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", OutMetaName(DlgFileName)) );
  58.     special_fopen_actions(OutMetaName(DlgFileName));
  59.  
  60.     fprintf(dlgFile, "<<\n");
  61.     fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);
  62.     fprintf(dlgFile, " *\n");
  63.     fprintf(dlgFile, " * Generated from:");
  64.     {int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}
  65.     fprintf(dlgFile, "\n");
  66.     fprintf(dlgFile, " *\n");
  67.     fprintf(dlgFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  68.     fprintf(dlgFile, " * Purdue University Electrical Engineering\n");
  69.     fprintf(dlgFile, " * With AHPCRC, University of Minnesota\n");
  70.     fprintf(dlgFile, " * ANTLR Version %s\n", Version);
  71.     fprintf(dlgFile, " */\n\n");
  72.     if ( GenCC )
  73.     {
  74.         if ( !UserDefdTokens ) fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
  75.         else fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);
  76.         fprintf(dlgFile, "#include \"%s\"\n", ATOKEN_H);
  77.         if ( GenAST ) fprintf(dlgFile, "#include \"%s\"\n", ASTBASE_H);
  78.         if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
  79.     }
  80.     else
  81.     {
  82.         fprintf(dlgFile, "#include <stdio.h>\n");
  83.         fprintf(dlgFile, "#define ANTLR_VERSION    %s\n", VersionDef);
  84.         if ( strcmp(ParserName, DefaultParserName)!=0 )
  85.             fprintf(dlgFile, "#define %s %s\n", DefaultParserName, ParserName);
  86.         if ( strcmp(ParserName, DefaultParserName)!=0 )
  87.             fprintf(dlgFile, "#include \"%s\"\n", RemapFileName);
  88.         if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
  89.         if ( FoundGuessBlk )
  90.         {
  91.             fprintf(dlgFile, "#define ZZCAN_GUESS\n");
  92.             fprintf(dlgFile, "#include <setjmp.h>\n");
  93.         }
  94.         if ( OutputLL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);
  95.         if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");
  96.         fprintf(dlgFile, "#include \"antlr.h\"\n");
  97.         if ( GenAST ) {
  98.             fprintf(dlgFile, "#include \"ast.h\"\n");
  99.         }
  100.         if ( UserDefdTokens )
  101.             fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);
  102.         /* still need this one as it has the func prototypes */
  103.         fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
  104.         fprintf(dlgFile, "#include \"dlgdef.h\"\n");
  105.         fprintf(dlgFile, "LOOKAHEAD\n");
  106.         fprintf(dlgFile, "void zzerraction()\n");
  107.         fprintf(dlgFile, "{\n");
  108.         fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);
  109.         fprintf(dlgFile, "\tzzadvance();\n");
  110.         fprintf(dlgFile, "\tzzskip();\n");
  111.         fprintf(dlgFile, "}\n");
  112.     }
  113.     fprintf(dlgFile, ">>\n\n");
  114.  
  115.     /* dump all actions */
  116.     if (LexActions != NULL)
  117.     {
  118.         for (p = LexActions->next; p!=NULL; p=p->next)
  119.         {
  120.             fprintf(dlgFile, "<<\n");
  121.             dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
  122.             fprintf(dlgFile, ">>\n");
  123.         }
  124.     }
  125.     /* dump all regular expression rules/actions (skip sentinel node) */
  126.     if ( ExprOrder == NULL ) {
  127.         warnNoFL("no regular expressions found in grammar");
  128.     }
  129.     else dumpLexClasses(dlgFile);
  130.     fprintf(dlgFile, "%%%%\n");
  131.     fclose( dlgFile );
  132. }
  133.  
  134. /* For each lexical class, scan ExprOrder looking for expressions
  135.  * in that lexical class.  Print out only those that match.
  136.  * Each element of the ExprOrder list has both an expr and an lclass
  137.  * field.
  138.  */
  139. void
  140. #ifdef __STDC__
  141. dumpLexClasses( FILE *dlgFile )
  142. #else
  143. dumpLexClasses( dlgFile )
  144. FILE *dlgFile;
  145. #endif
  146. {
  147.     int i;
  148.     TermEntry *t;
  149.     ListNode *p;
  150.     Expr *q;
  151.  
  152.     for (i=0; i<NumLexClasses; i++)
  153.     {
  154.         fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].classnum);
  155.         for (p=ExprOrder->next; p!=NULL; p=p->next)
  156.         {
  157.             q = (Expr *) p->elem;
  158.             if ( q->lclass != i ) continue;
  159.             lexmode(i);
  160.             t = (TermEntry *) hash_get(Texpr, q->expr);
  161.             require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );
  162.             if ( t->token == EpToken ) continue;
  163.             fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));
  164.             /* replace " killed by StripQuotes() */
  165.             q->expr[ strlen(q->expr) ] = '"';
  166.             if ( !GenCC ) {
  167.                 if ( TokenString(t->token) != NULL )
  168.                     fprintf(dlgFile, "\t\tNLA = %s;\n", TokenString(t->token));
  169.                 else
  170.                     fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);
  171.             }
  172.             if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );
  173.             if ( GenCC ) {
  174.                 if ( TokenString(t->token) != NULL )
  175.                     fprintf(dlgFile, "\t\treturn %s;\n", TokenString(t->token));
  176.                 else
  177.                     fprintf(dlgFile, "\t\treturn (TokenType)%d;\n", t->token);
  178.             }
  179.             fprintf(dlgFile, "\t>>\n\n");
  180.         }
  181.     }
  182. }
  183.  
  184. /* Generate a list of #defines && list of struct definitions for
  185.  * aggregate retv's */
  186. void
  187. #ifdef __STDC__
  188. genDefFile( void )
  189. #else
  190. genDefFile( )
  191. #endif
  192. {
  193.     int i;
  194.  
  195.     /* If C++ mode and #tokdef used, then don't need anything in here since
  196.      * C++ puts all definitions in the class file name.
  197.      */
  198.     if ( GenCC && UserTokenDefsFile ) return;
  199.  
  200.     DefFile = fopen(OutMetaName(DefFileName), "w");
  201.     require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", OutMetaName(DefFileName)) );
  202.     special_fopen_actions(OutMetaName(DefFileName));
  203.  
  204.     fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName);
  205.     fprintf(DefFile, " *\n");
  206.     fprintf(DefFile, " * Generated from:");
  207.     for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);
  208.     fprintf(DefFile, "\n");
  209.     fprintf(DefFile, " *\n");
  210.     fprintf(DefFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  211.     fprintf(DefFile, " * Purdue University Electrical Engineering\n");
  212.     fprintf(DefFile, " * ANTLR Version %s\n", Version);
  213.     fprintf(DefFile, " */\n");
  214. /*    if ( TokenString((TokenInd!=NULL?TokenInd[EofToken]:EofToken))!=NULL )
  215.         fprintf(DefFile, "#define %s %d\n", TokenString((TokenInd!=NULL?TokenInd[EofToken]:EofToken)), (TokenInd!=NULL?TokenInd[EofToken]:EofToken));*/
  216.     
  217.     if ( !UserDefdTokens )
  218.     {
  219.         int first=1;
  220.  
  221.         if ( GenCC ) fprintf(DefFile, "enum TokenType {\n");
  222.         for (i=1; i<TokenNum; i++)
  223.         {
  224.             /* Don't do EpToken or expr w/o labels */
  225.             if ( TokenString(i)!=NULL && i != EpToken )
  226.             {
  227.                 TermEntry *p;
  228.                 
  229.                 if ( WarningLevel>1 )
  230.                 {
  231.                     int j;
  232.                     /* look in all lexclasses for the reg expr */
  233.                     for (j=0; j<NumLexClasses; j++)
  234.                     {
  235.                         lexmode(j);
  236.                         if ( ExprString(i)!=NULL ) break;
  237.                     }
  238.                     if ( j>=NumLexClasses )
  239.                     {
  240.                         warnNoFL(eMsg1("token label has no associated rexpr: %s",TokenString(i)));
  241.                     }
  242.                 }
  243.                 require((p=(TermEntry *)hash_get(Tname, TokenString(i))) != NULL,
  244.                         "token not in sym tab when it should be");
  245.                 if ( !p->classname )
  246.                 {
  247.                     if ( GenCC ) {
  248.                         if ( !first ) fprintf(DefFile, ",\n");
  249.                         first = 0;
  250.                         fprintf(DefFile, "\t%s=%d", TokenString(i), i);
  251.                     }
  252.                     else
  253.                         fprintf(DefFile, "#define %s %d\n", TokenString(i), i);
  254.                 }
  255.             }
  256.         }
  257.         if ( GenCC ) fprintf(DefFile, "};\n");
  258.     }
  259.  
  260.     if ( !GenCC ) GenRulePrototypes(DefFile, SynDiag);
  261. }
  262.  
  263. void
  264. #ifdef __STDC__
  265. GenRemapFile( void )
  266. #else
  267. GenRemapFile( )
  268. #endif
  269. {
  270.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  271.     {
  272.         FILE *f;
  273.         int i;
  274.  
  275.         f = fopen(OutMetaName(RemapFileName), "w");
  276.         require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", OutMetaName(RemapFileName)) );
  277.         special_fopen_actions(OutMetaName(RemapFileName));
  278.  
  279.         fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName);
  280.         fprintf(f, " *\n");
  281.         fprintf(f, " * Generated from:");
  282.         for (i=0; i<NumFiles; i++) fprintf(f, " %s", FileStr[i]);
  283.         fprintf(f, "\n");
  284.         fprintf(f, " *\n");
  285.         fprintf(f, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  286.         fprintf(f, " * Purdue University Electrical Engineering\n");
  287.         fprintf(f, " * ANTLR Version %s\n", Version);
  288.         fprintf(f, " */\n");
  289.  
  290.         GenRuleFuncRedefs(f, SynDiag);
  291.         GenPredefinedSymbolRedefs(f);
  292.         if ( GenAST ) GenASTSymbolRedefs(f);
  293.         GenSetRedefs(f);
  294.  
  295.         fclose(f);
  296.     }
  297. }
  298.  
  299. /* Generate a bunch of #defines that rename all functions to be "ParserName_func" */
  300. void
  301. #ifdef __STDC__
  302. GenRuleFuncRedefs( FILE *f, Junction *p )
  303. #else
  304. GenRuleFuncRedefs( f, p )
  305. FILE *f;
  306. Junction *p;
  307. #endif
  308. {
  309.     fprintf(f, "\n/* rename rule functions to be 'ParserName_func' */\n");
  310.     while ( p!=NULL )
  311.     {
  312.         fprintf(f, "#define %s %s_%s\n", p->rname, ParserName, p->rname);
  313.         p = (Junction *)p->p2;
  314.     }
  315. }
  316.  
  317. /* Generate a bunch of #defines that rename all standard symbols to be
  318.  * "ParserName_symbol".  The list of standard symbols to change is in
  319.  * globals.c.
  320.  */
  321. void
  322. #ifdef __STDC__
  323. GenPredefinedSymbolRedefs( FILE *f )
  324. #else
  325. GenPredefinedSymbolRedefs( f )
  326. FILE *f;
  327. #endif
  328. {
  329.     char **p;
  330.  
  331.     fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n");
  332.     for (p = &StandardSymbols[0]; *p!=NULL; p++)
  333.     {
  334.         fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
  335.     }
  336. }
  337.  
  338. /* Generate a bunch of #defines that rename all AST symbols to be
  339.  * "ParserName_symbol".  The list of AST symbols to change is in
  340.  * globals.c.
  341.  */
  342. void
  343. #ifdef __STDC__
  344. GenASTSymbolRedefs( FILE *f )
  345. #else
  346. GenASTSymbolRedefs( f )
  347. FILE *f;
  348. #endif
  349. {
  350.     char **p;
  351.  
  352.     fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n");
  353.     for (p = &ASTSymbols[0]; *p!=NULL; p++)
  354.     {
  355.         fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
  356.     }
  357. }
  358.  
  359. /* redefine all sets generated by ANTLR; WARNING:  'zzerr', 'setwd' must match
  360.  * use in bits.c (DumpSetWd() etc...)
  361.  */
  362. void
  363. #ifdef __STDC__
  364. GenSetRedefs( FILE *f )
  365. #else
  366. GenSetRedefs( f )
  367. FILE *f;
  368. #endif
  369. {
  370.     int i;
  371.  
  372.     for (i=1; i<=wordnum; i++)
  373.     {
  374.         fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i);
  375.     }
  376.     for (i=1; i<=esetnum; i++)
  377.     {
  378.         fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i);
  379.     }
  380. }
  381.  
  382. /* Find all return types/parameters that require structs and def
  383.  * all rules with ret types.
  384.  */
  385. void
  386. #ifdef __STDC__
  387. GenRulePrototypes( FILE *f, Junction *p )
  388. #else
  389. GenRulePrototypes( f, p )
  390. FILE *f;
  391. Junction *p;
  392. #endif
  393. {
  394.     int i;
  395.  
  396.     i = 1;
  397.     while ( p!=NULL )
  398.     {
  399.         if ( p->ret != NULL )
  400.         {
  401.             if ( HasComma(p->ret) )
  402.             {
  403.                 DumpRetValStruct(f, p->ret, i);
  404.             }
  405.             fprintf(f, "\n#ifdef __STDC__\n");
  406.             if ( HasComma(p->ret) )
  407.             {
  408.                 fprintf(f, "extern struct _rv%d", i);
  409.             }
  410.             else
  411.             {
  412.                 fprintf(f, "extern ");
  413.                 DumpType(p->ret, f);
  414.             }
  415.             fprintf(f, " %s%s(", RulePrefix, p->rname);
  416.             if ( p->pdecl != NULL || GenAST )
  417.             {
  418.                 if ( GenAST ) {
  419.                     fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
  420.                 }
  421.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  422.             }
  423.             else fprintf(f, "void");
  424.             fprintf(f, ");\n");
  425.             fprintf(f, "#else\n");
  426.             if ( HasComma(p->ret) )
  427.             {
  428.                 fprintf(f, "extern struct _rv%d", i);
  429.             }
  430.             else
  431.             {
  432.                 fprintf(f, "extern ");
  433.                 DumpType(p->ret, f);
  434.             }
  435.             fprintf(f, " %s%s();\n", RulePrefix, p->rname);
  436.             fprintf(f, "#endif\n");
  437.         }
  438.         else
  439.         {
  440.             fprintf(f, "\n#ifdef __STDC__\n");
  441.             fprintf(f, "void %s%s(", RulePrefix, p->rname);
  442.             if ( p->pdecl != NULL || GenAST )
  443.             {
  444.                 if ( GenAST ) {
  445.                     fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
  446.                 }
  447.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  448.             }
  449.             else fprintf(f, "void");
  450.             fprintf(f, ");\n");
  451.             fprintf(f, "#else\n");
  452.             fprintf(f, "extern void %s%s();\n", RulePrefix, p->rname);
  453.             fprintf(f, "#endif\n");
  454.         }
  455.         i++;
  456.         p = (Junction *)p->p2;
  457.     }
  458. }
  459.  
  460. /* Define all rules in the class.h file; generate any required
  461.  * struct definitions first, however.
  462.  */
  463. void
  464. #ifdef __STDC__
  465. GenRuleMemberDeclarationsForCC( FILE *f, Junction *q )
  466. #else
  467. GenRuleMemberDeclarationsForCC( f, q )
  468. FILE *f;
  469. Junction *q;
  470. #endif
  471. {
  472.     Junction *p = q;
  473.     int i;
  474.  
  475.     /* Dump return value structs */
  476.     fprintf(f, "private:\n");
  477.     i = 1;
  478.     while ( p!=NULL )
  479.     {
  480.         if ( p->ret != NULL )
  481.         {
  482.             if ( HasComma(p->ret) )
  483.             {
  484.                 DumpRetValStruct(f, p->ret, i);
  485.             }
  486.         }
  487.         i++;
  488.         p = (Junction *)p->p2;
  489.     }
  490.  
  491.     /* Dump member func defs && CONSTRUCTOR */
  492.     fprintf(f, "public:\n");
  493.     fprintf(f, "\t%s(ANTLRTokenBuffer *input);\n", CurrentClassName);
  494.     fprintf(f, "\t%s(ANTLRTokenBuffer *input, TokenType eof);\n",
  495.                CurrentClassName);
  496.     i = 1;
  497.     p = q;
  498.     while ( p!=NULL )
  499.     {
  500.         if ( p->ret != NULL )
  501.         {
  502.             if ( HasComma(p->ret) )
  503.             {
  504.                 fprintf(f, "\tstruct _rv%d", i);
  505.             }
  506.             else
  507.             {
  508.                 fprintf(f, "\t");
  509.                 DumpType(p->ret, f);
  510.             }
  511.             fprintf(f, " %s(", p->rname);
  512.             if ( p->pdecl != NULL || GenAST )
  513.             {
  514.                 if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");
  515.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  516.             }
  517.             fprintf(f, ");\n");
  518.         }
  519.         else
  520.         {
  521.             fprintf(f, "\tvoid %s(", p->rname);
  522.             if ( p->pdecl != NULL || GenAST )
  523.             {
  524.                 if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");
  525.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  526.             }
  527.             fprintf(f, ");\n");
  528.         }
  529.         i++;
  530.         p = (Junction *)p->p2;
  531.     }
  532. }
  533.  
  534. /* Given a list of ANSI-style parameter declarations, print out a
  535.  * comma-separated list of the symbols (w/o types).
  536.  * Basically, we look for a comma, then work backwards until start of
  537.  * the symbol name.  Then print it out until 1st non-alnum char.  Now,
  538.  * move on to next parameter.
  539.  */
  540. void
  541. #ifdef __STDC__
  542. DumpListOfParmNames( char *pdecl, FILE *output )
  543. #else
  544. DumpListOfParmNames( pdecl, output )
  545. char *pdecl;
  546. FILE *output;
  547. #endif
  548. {
  549.     int firstTime = 1, done = 0;
  550.     require(output!=NULL, "DumpListOfParmNames: NULL parm");
  551.  
  552.     if ( pdecl == NULL ) return;
  553.     while ( !done )
  554.     {
  555.         if ( !firstTime ) putc(',', output);
  556.         done = DumpNextNameInDef(&pdecl, output);
  557.         firstTime = 0;
  558.     }
  559. }
  560.  
  561. /* given a list of parameters or return values, dump the next
  562.  * name to output.  Return 1 if last one just printed, 0 if more to go.
  563.  */
  564. int
  565. #ifdef __STDC__
  566. DumpNextNameInDef( char **q, FILE *output )
  567. #else
  568. DumpNextNameInDef( q, output )
  569. char **q;
  570. FILE *output;
  571. #endif
  572. {
  573.     char *p = *q;        /* where did we leave off? */
  574.     int done=0;
  575.  
  576.     while ( *p!='\0' && *p!=',' ) p++;        /* find end of decl */
  577.     if ( *p == '\0' ) done = 1;
  578.     while ( !isalnum(*p) && *p!='_' ) --p;    /* scan back until valid var character */
  579.     while ( isalnum(*p) || *p=='_' ) --p;    /* scan back until beginning of variable */
  580.     p++;                        /* move to start of variable */
  581.     while ( isalnum(*p) || *p=='_'  ) {putc(*p, output); p++;}
  582.     while ( *p!='\0' && *p!=',' ) p++;        /* find end of decl */
  583.     p++;                /* move past this parameter */
  584.  
  585.     *q = p;                /* record where we left off */
  586.     return done;
  587. }
  588.  
  589. /* Given a list of ANSI-style parameter declarations, dump K&R-style
  590.  * declarations, one per line for each parameter.  Basically, convert
  591.  * comma to semi-colon, newline.
  592.  */
  593. void
  594. #ifdef __STDC__
  595. DumpOldStyleParms( char *pdecl, FILE *output )
  596. #else
  597. DumpOldStyleParms( pdecl, output )
  598. char *pdecl;
  599. FILE *output;
  600. #endif
  601. {
  602.     require(output!=NULL, "DumpOldStyleParms: NULL parm");
  603.  
  604.     if ( pdecl == NULL ) return;
  605.     while ( *pdecl != '\0' )
  606.     {
  607.         if ( *pdecl == ',' )
  608.         {
  609.             pdecl++;
  610.             putc(';', output); putc('\n', output);
  611.             while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;
  612.         }
  613.         else {putc(*pdecl, output); pdecl++;}
  614.     }
  615.     putc(';', output);
  616.     putc('\n', output);
  617. }
  618.  
  619. /* Take in a type definition (type + symbol) and print out type only */
  620. void
  621. #ifdef __STDC__
  622. DumpType( char *s, FILE *f )
  623. #else
  624. DumpType( s, f )
  625. char *s;
  626. FILE *f;
  627. #endif
  628. {
  629.     char *p, *end;
  630.     require(s!=NULL, "DumpType: invalid type string");
  631.  
  632.     p = &s[strlen(s)-1];        /* start at end of string and work back */
  633.     /* scan back until valid variable character */
  634.     while ( !isalnum(*p) && *p!='_' ) --p;
  635.     /* scan back until beginning of variable */
  636.     while ( isalnum(*p) || *p=='_' ) --p;
  637.     if ( p<=s )
  638.     {
  639.         warnNoFL(eMsg1("invalid parameter/return value: '%s'",s));
  640.         return;
  641.     }
  642.     end = p;                    /* here is where we stop printing alnum */
  643.     p = s;
  644.     while ( p!=end ) {putc(*p, f); p++;} /* dump until just before variable */
  645.     while ( *p!='\0' )                     /* dump rest w/o variable */
  646.     {
  647.         if ( !isalnum(*p) && *p!='_' ) putc(*p, f);
  648.         p++;
  649.     }
  650. }
  651.  
  652. /* check to see if string e is a word in string s */
  653. int
  654. #ifdef __STDC__
  655. strmember( char *s, char *e )
  656. #else
  657. strmember( s, e )
  658. char *s;
  659. char *e;
  660. #endif
  661. {
  662.     register char *p;
  663.     require(s!=NULL&&e!=NULL, "strmember: NULL string");
  664.     
  665.     if ( *e=='\0' ) return 1;   /* empty string is always member */
  666.     do {
  667.     while ( *s!='\0' && !isalnum(*s) && *s!='_' )
  668.     ++s;
  669.     p = e;
  670.     while ( *p!='\0' && *p==*s ) {p++; s++;}
  671.     if ( *p=='\0' ) {
  672.         if ( *s=='\0' ) return 1;
  673.         if ( !isalnum (*s) && *s != '_' ) return 1;
  674.     }
  675.     while ( isalnum(*s) || *s == '_' )
  676.     ++s;
  677.     } while ( *s!='\0' );
  678.     return 0;
  679. }
  680.  
  681. int
  682. #ifdef __STDC__
  683. HasComma( char *s )
  684. #else
  685. HasComma( s )
  686. char *s;
  687. #endif
  688. {
  689.     while (*s!='\0')
  690.         if ( *s++ == ',' ) return 1;
  691.     return 0;
  692. }
  693.  
  694. void
  695. #ifdef __STDC__
  696. DumpRetValStruct( FILE *f, char *ret, int i )
  697. #else
  698. DumpRetValStruct( f, ret, i )
  699. FILE *f;
  700. char *ret;
  701. int i;
  702. #endif
  703. {
  704.     fprintf(f, "\nstruct _rv%d {\n", i);
  705.     while ( *ret != '\0' )
  706.     {
  707.          while ( *ret==' ' || *ret=='\t' ) ret++; /* ignore white */
  708.          putc('\t', f);
  709.          while ( *ret!=',' && *ret!='\0' ) putc(*ret++, f);
  710.          if ( *ret == ',' ) {putc(';', f); putc('\n', f); ret++;}
  711.     }
  712.     fprintf(f, ";\n};\n");
  713. }
  714.  
  715. /* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */
  716. char *
  717. #ifdef __STDC__
  718. StripQuotes( char *s )
  719. #else
  720. StripQuotes( s )
  721. char *s;
  722. #endif
  723. {
  724.     if ( *s == '"' )
  725.     {
  726.         s[ strlen(s)-1 ] = '\0';    /* remove last quote */
  727.         return( s+1 );                /* return address past initial quote */
  728.     }
  729.     return( s );
  730. }
  731.  
  732.